iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 3
0

建立工作區

首先,要先在電腦的某處建立屬於自己的工作區。未來我們的工作都會在這邊進行。

mkdir rafax
cd rafax

建立 composer 相關環境

composer 建立 composer.json (設定檔)

composer init # 依照自己的想法輸入設定檔,以下作為參考

# Package name (<vendor>/<name>): chivincent/rafax
# Description []: iThome 2018 ironman challenge. 
# Author: Vincent Chi <song374561@chivincent.net>
# Minimum Stability []: stable
# Package Type []: project
# License []: MIT
# Would you like to define your dependencies (require) interactively: no
# Would you link to define your dev dependencies (require-dev) interactively: no

composer update # 建立 vendor/autoload.php

# 注意:此時可能會出現 "No locakfile found. Unable to read locked packages"
# 這是因為我們尚未安裝任何 package,故未能產生 composer.lock,忽略即可

至此,你的 composer.json 應該類似於下面的結構

{
    "name": "chivincent/rafax",
    "description": "iThome 2018 ironman challenge.",
    "type": "project",
    "license": "MIT",
    "authors": [
        {
            "name": "Vincent Chi",
            "email": "song374561@chivincent.net"
        }
    ],
    "minimum-stability": "stable",
    "require": {}
}

Hello World

緊接著,我們先建立這個框架第一個程式,依照慣例通常要是 Hello World 。建立 index.php 作為程式的入口點。

// rafax/index.php
<?php

echo 'Hello World'.PHP_EOL;

我們可以啟動 PHP 內置的網頁服務器(Built-in Web Server)來瀏覽其結果

php -S localhost:10000

安全警告

我們發現,如果連接到 http://localhost:10000/composer.json 即可看到我們專案的 composer.json ,而且可以存取 .git/,這會造成過度的資訊洩露。(儘管現在沒有什麼資訊可以洩露)

一般而言,我們會建立一個獨立的資料夾,用來作為公開的根目錄,在此我們取名為 public ,然後將 index.php 移至 public/ 資料夾下,並且在 public/ 資料夾中重新啟動 PHP 內置網頁伺服器

mkdir public
mv index.php public/

php -S localhost:10000 -t public

引入 autoload.php

為了確保我們未來可以使用 composer 的套件,所以必須在應用程式的入口點(此案例中目前僅有 public/index.php 一個入口點)中優先引入 vendor/autoload.php

// rafax/public/index.php
<?php

require __DIR__ . '/../vendor/autoload.php';

echo 'Hello World'.PHP_EOL;

討論:為什麼要用 require 而不是 include;為什麼要用 require 而不是 require_once

require 會在引入時發生錯誤時(例如被引入目標不存在)拋出 Error 且終止應用程式,但 include 僅會拋出 Warning 且會讓程式繼續向下執行。

對於 composer autoloader 這類無論如何都必須被引入的腳本而言,如果其中發生錯誤應該被提前得知,並且中止應用程式。

composer autoloader 無論在什麼情況下,都應該只被引入一次,以這層意義來看的話其實用 requirerequire_once 都是可以接受的。

然而隨著專案規模的擴大,未來可能會搞不清楚目前位置是否已經引用過 autoload.php ,若一直都是靠著使用 require_once ,因為在執行時期完全沒有任何警告或錯誤,以致於造成冗餘程式碼。

為了避免這樣的情況,當引用 autoload.php 時都建議使用 require ,如果有重複定義時就會由 PHP 直譯器拋出 Fatal error,進而提醒自己避免冗餘程式碼的出現。

討論:為什麼要用 __DIR__,而不是使用 dirname(__FILE__)

__DIR__ 出現於 PHP 5.3 之後,基本上功能與 dirname(__FILE__) 是完全相同的。

但是這邊要考量一點:__DIR__ 是屬於魔術常數(Magic constants),會在編譯時期(compile-time)被解析,而 dirname(__FILE__) 則是屬於函式呼叫(function-call),是在執行時期(execution-time)被解析。

就以理論角度而言,__DIR__ 的效率應該要比 dirname(__FILE__) 來得高,然而站在編譯器優化的角度來看,其實兩者效率是差不多,甚至是相同的,不過站在程式設計的觀點,它並非一個需要用 function call 解析的路徑,因為 autoload.php 一直都在同一個位置,所以通常是採用 __DIR__ 做路徑的設定。

參考資料

  1. Stack Overflow: Is there any difference between __DIR__ and dirname(__FILE__) in PHP?
  2. Syun: [PHP]include 與 require 的差別

上一篇
規畫
下一篇
Hello World, Hello My Framework
系列文
重新理解 PHP:從頭打造 Web Framework9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言